import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router';
import _ from 'lodash';
import { connect } from 'react-redux';
import cn from 'classnames';
import './index.less';
import EraserPng from './images/eraser.png';
import { Link } from 'react-router-dom';
import {
  Button,
  Checkbox,
  Icon,
  Input,
  InputNumber,
  Modal,
  Radio,
  Select,
  Spin,
  TimePicker,
  Tooltip,
  message
} from 'antd';
const { confirm } = Modal;
import { descriptions, detectionMinTime } from './constant';
import { NavLink } from 'react-router-dom';
import {
  IPV4_CIDE_RE,
  IPV6_CIDE_RE,
  IP_INTERVAL_RE,
  IP_RE,
  IP_V6,
  NAME_RE,
  TASK_PRIORITY_MAP,
  DOMAIN_RE,
  FULL_URL_RE
} from '@util/constants';
import {
  addDetectionTask,
  addVulDetectionTask,
  getAllStrategies,
  getAllHasPocOnedayList,
  getTargetList
} from '@api/task';
import { getNetConfig } from '@api/netConfig';
import CheckboxSelect from '@components/checkbox-select';
import TaskLimitDate from '@components/task-limit-date';
import checkDetectionTime from '@util/checkDetectionTime';
import { bindActionCreators } from 'redux';
import { actions as assetManageActions } from '@containers/asset-manage/reducer';
import { getAllDicts } from '@api/dict';

import RenderProbeStrategy from './component/render-probe-strategy';
import ScanRate from './component/scan-rate';
import isClusterModel from '@components/is-cluster-model';

const TextArea = Input.TextArea;
const RadioGroup = Radio.Group;
const prefixCls = 'add-task-form';
const scanList = [{ label: '自动分发', value: 'auto' }];
const AppTaskForm = props => {
  const {
    allSite,
    allSiteTitle,
    typeName,
    loadDetectionCache,
    history,
    callback,
    sites,
    description,
    isCluster,
    hasCluster
  } = props;
  const [name, setName] = useState('');
  const [queryType, setQueryType] = useState('custom');
  const [ipRangesModalVisible, setIpRangesModalVisible] = useState(false);
  const [ipRangesSpinning, setIpRangesSpinning] = useState(false);
  const [ipRanges, setIpRanges] = useState([]);
  const [ips, setIps] = useState([]);
  const [selectedIpRangesKeys, setSelectedIpRangesKeys] = useState();
  const [isCycle, setIsCycle] = useState(false);
  const [intervalTime, setIntervalTime] = useState(1);
  const [intervalUnit, setIntervalUnit] = useState('day');
  const [startAt, setStartAt] = useState();
  const [endAt, setEndAt] = useState();
  const [timing, setTiming] = useState({ dailyStart: '', dailyEnd: '' });
  const [priority, setPriority] = useState('middle');
  // 网口变量
  const [interfaces, setInterfaces] = useState();
  // 网口下拉列表
  const [interfacesList, setInterfacesList] = useState([]);
  // 漏扫策略
  const [selectedTemplateId, setSelectedTemplateId] = useState('');
  const [onedays, setOnedays] = useState([]);
  const [selectedOnedays, setSelectedOnedays] = useState('');
  const [dictsGroups, setDictsGroups] = useState({});
  const [dictSelect, setDictSelect] = useState({ username: [], password: [] });
  const [strategyTemplates, setStrategyTemplates] = useState([]);
  const [ignoreType, setIgnoreType] = useState(true);
  const [siteIdList, setSiteIdList] = useState();
  const [isSelectVulTask, setIsSelectVulTask] = useState();
  const [scanNodes] = useState('auto');
  // 错误数据
  const [errors, setErrors] = useState({
    nameError: '',
    ipsError: '',
    ipRangesError: '',
    timeRangeError: '',
    detectionTimeError: ''
  });
  const RenderProbeStrategyRef = useRef();
  const ScanRateRef = useRef();

  const DICT_OPTIONS = [
    {
      name: '用户名字典',
      key: 'username'
    },
    {
      name: '密码字典',
      key: 'password'
    }
  ];
  const onNameChange = e => {
    const name = e.target.value;
    let nameError = '';
    if (!name) {
      nameError = '任务名不能为空';
    } else if (name.length > 32) {
      nameError = '您输入的内容超过32个字符限制';
    } else if (!NAME_RE.test(name)) {
      nameError = '您输入的格式有误，仅支持中文、英文、数字、特殊字符 - 、— \\ _ / ：~';
    }
    setName(name);
    setErrors({ ...errors, nameError });
  };

  const loadIpRanges = () => {
    setIpRangesSpinning(true);
    getTargetList({
      page: 1,
      pageSize: 199
    }).then(res => {
      const ipRanges = _.get(res, 'data.data.list', []);
      setIpRanges(ipRanges);
      setIpRangesSpinning(false);
    });
  };

  const onTargetTypeChange = e => {
    const queryType = e.target.value;
    setQueryType(queryType);
    if (queryType === 'targetGroup') {
      setIpRangesModalVisible(true);
    }
    loadIpRanges();
  };

  const targetCountSum = (value, targets, targetGroup = false) => {
    let ipsError = value.length ? '' : '探测目标不能为空';
    let ipRangesError = value.length ? '' : '探测目标不能为空';
    let targetCount = 0;

    for (let i = 0; i < targets.length; i++) {
      if (targetCount > 131072) {
        break;
      }
      const target = targets[i];
      if (
        DOMAIN_RE.test(target) ||
        IP_RE.test(target) ||
        IP_V6.test(target) ||
        FULL_URL_RE.test(target)
      ) {
        targetCount += 1;
      } else if (IPV4_CIDE_RE.test(target)) {
        const prefixLength = target.split('/')[1];
        targetCount += Math.pow(2, 32 - Number(prefixLength));
      } else if (IPV6_CIDE_RE.test(target)) {
        const prefixLength = target.split('/')[1];
        targetCount += Math.pow(2, 128 - Number(prefixLength));
        if (prefixLength < 118) {
          ipsError = '单个IPv6最大支持1024个地址';
          break;
        }
      } else if (IP_INTERVAL_RE.test(target, true)) {
        const targetGroup = target.split('-');
        const startIPArr = targetGroup[0].split('.').map(Number);
        const endIPArr = targetGroup[1].split('.').map(Number);
        if (startIPArr[0] !== endIPArr[0] || endIPArr[1] !== startIPArr[1]) {
          targetCount = Infinity;
          ipsError = '起始IP和末尾IP只允许最后两位不同';
          break;
        }
        const rangeC = endIPArr[2] - startIPArr[2];
        const rangeD = endIPArr[3] - startIPArr[3];
        const ipCount = rangeC * Math.pow(2, 8) + rangeD;
        if (ipCount <= 0) {
          ipsError = '起始IP必须小于末尾IP';
          break;
        } else {
          targetCount += ipCount;
        }
      } else {
        ipsError = '探测目标格式错误';
        break;
      }
    }

    if (targetCount > 131072 && !ipsError && !targetGroup) {
      ipsError = `探测目标为:${targetCount}个，单个任务最多允许针对131072个目标进行探测`;
    } else if (targetCount > 131072 && !ipRangesError) {
      if (targetGroup) {
        return targetCount;
      }
    }
    setErrors({ ...errors, ipsError });
  };
  const onTargetsChange = e => {
    const value = e.target.value;
    const targets = _.split(value, '\n');
    targetCountSum(value, targets);
    setQueryType('custom');
    setIps(targets);
  };

  const clearTarget = () => {
    setQueryType('custom');
    setIps([]);
    setErrors({});
    setSelectedIpRangesKeys([]);
    setIpRangesSpinning(false);
  };

  const onDateStartChange = startAt => {
    setStartAt(startAt);
  };

  const onDateEndChange = endAt => {
    setEndAt(endAt);
  };

  const checkTime = () => {
    if (errors.timeRangeError) {
      return;
    }
    const hasDetectEnoughTime = checkDetectionTime({ timing, startAt, endAt });
    setErrors({
      ...errors,
      detectionTimeError: hasDetectEnoughTime ? '' : '运行时间小于30分钟，请重新选择'
    });
  };

  const onTimeRangeChange = (key, time) => {
    const dtiming = timing || {};
    let { dailyStart, dailyEnd } = dtiming;
    let timeRangeError = '';
    if (key === 'dailyStart') {
      dailyStart = time;
    } else {
      dailyEnd = time;
    }
    if (!dailyEnd) {
      timeRangeError = '请选择终止时间';
    }
    if (!dailyStart) {
      timeRangeError = '请选择起始时间';
    }

    if (dailyStart && dailyEnd) {
      const gap = dailyEnd - dailyStart;

      if (gap < detectionMinTime && gap > -detectionMinTime) {
        timeRangeError = '终止时间要大于起始时间30分钟以上';
      }
    }
    setTiming({ dailyStart, dailyEnd });
    setErrors({ ...errors, timeRangeError });
  };

  const loadOnedays = () => {
    getAllHasPocOnedayList().then(res => {
      const onedays = _.get(res, 'data.data.list', []);
      setOnedays(onedays);
    });
  };

  const onSelectOnedays = keys => {
    setSelectedOnedays(keys);
  };

  const onChangeTemplate = checkedTemplateId => {
    setSelectedTemplateId(checkedTemplateId);
  };

  const allDicts = () => {
    getAllDicts().then(res => {
      const list = _.get(res, 'data.data.list', []);
      const dictsGroups = {};
      list.forEach(d => {
        dictsGroups[d._id] = [].concat(d.dicts);
      });
      const dictSelect = {};
      DICT_OPTIONS.forEach(({ key }) => {
        const hasDict = !_.isEmpty(dictsGroups[key]);
        let builtInDict = _.find(dictsGroups[key], 'isBuiltIn');
        builtInDict = hasDict && builtInDict ? builtInDict : {};
        dictSelect[key] = builtInDict._id || '';
      });
      setDictsGroups(dictsGroups);
      setDictSelect(dictSelect);
    });
  };

  const renderDist = () => {
    return (
      <>
        {DICT_OPTIONS.map(({ name, key }) => {
          const hasDict = !_.isEmpty(dictsGroups[key]);
          return (
            <div className={'item'} key={key}>
              <div className={'item-title'}>{name}</div>
              <Select value={dictSelect[key]} style={{ width: 180 }}>
                {hasDict &&
                  dictsGroups[key].map(dict => {
                    return (
                      <Select.Option value={dict._id} type={key} key={dict._id}>
                        {dict.name}
                      </Select.Option>
                    );
                  })}
              </Select>
            </div>
          );
        })}
        <div style={{ float: 'left', marginTop: -100, marginLeft: 400 }}>
          <Link to="/asset-config/dict-config">配置字典</Link>
        </div>
      </>
    );
  };

  // 下发
  const submit = async () => {
    await isClusterModel();
    let cloneErrors = errors;
    // 获取两个子组件的内容和数据
    let probeStrategyData = RenderProbeStrategyRef.current;
    let ScanRateData = ScanRateRef.current;
    // 校验名称
    if (!name) {
      cloneErrors.nameError = '任务名称不能为空';
    }
    // 检验探测目标
    const target = {};
    switch (queryType) {
      case 'custom':
        if (
          _.isEmpty(ips) &&
          !['notUpdateIn1Days', 'notUpdateIn7Days', 'notUpdateIn30Days'].includes(typeName)
        ) {
          cloneErrors.ipsError = '探测目标不能为空';
        }
        if (!_.isEmpty(ips)) {
          target.list = ips.filter(i => i);
        }
        break;
      case 'targetGroup': {
        const selectedIpRanges = _.filter(ipRanges, range =>
          _.includes(selectedIpRangesKeys, range._id)
        );
        const sum = targetCountSum(
          selectedIpRanges,
          _.flatten(_.map(selectedIpRanges, 'ips')),
          true
        );
        if (sum) {
          cloneErrors.ipRangesError = `探测目标为:${sum}个，单个任务最多允许针对131072个目标进行探测`;
        }
        target.list = _.flatten(_.map(selectedIpRanges, 'ips'));
        if (_.isEmpty(target.list)) {
          cloneErrors.ipRangesError = '探测目标不能为空';
        }
        target.targetGroupIdList = selectedIpRangesKeys;
        // 先校验是否选中探测目标，再删除
        delete target.list;
        break;
      }
      default:
        return;
    }
    target.queryType = queryType;
    cloneErrors = { ...cloneErrors, ...probeStrategyData.data.erro, ...ScanRateData.data.erro };
    setErrors({ ...cloneErrors });
    //  判断是否有报错
    if (!_.isEmpty(_.pickBy(errors, Boolean))) {
      return;
    }
    if (!probeStrategyData.data.check()) {
      return;
    }
    const { maxImumConnection, scanBandwidth } = ScanRateData.data;
    const {
      detectionPortId,
      fingerprintDetection,
      portDetectionOnly,
      protocolType,
      detectionPortList,
      depthDetect,
      ignorePrinterPortCheck
    } = probeStrategyData.data;
    let api = typeName === 'VulDetect' ? addVulDetectionTask : addDetectionTask;
    let body = {
      name,
      target,
      isCycle,
      interface: interfaces,
      priority,
      portsType: detectionPortId && detectionPortId !== '01' ? 'template' : 'custom',
      connectionCount: maxImumConnection * 10000,
      speedLimit: scanBandwidth,
      webFingerprintDetection: fingerprintDetection,
      protocol: protocolType,
      ports: detectionPortList,
      scanType: 'Zoomeye',
      depthDetect: depthDetect,
      portDetectionOnly: portDetectionOnly || false,
      ignorePrinterPortCheck: ignorePrinterPortCheck || false
    };
    if (typeName === 'VulDetect') {
      delete body.scanType;
      delete body.portDetectionOnly;
      // 如果是漏扫并且不是自定义或者自动匹配
      if (selectedTemplateId !== '01' && selectedTemplateId !== '00') {
        body.oneday = {
          queryType: 'template',
          templateId: selectedTemplateId
        };
      } else {
        body.oneday = {
          queryType: 'list',
          onedayIdList: selectedOnedays
        };
      }
    }
    // 判断是否选择了漏扫策略
    detectionPortId && detectionPortId !== '01'
      ? (body.selectedPortTemplate = detectionPortId)
      : delete body.detectionPortId;
    ignoreType ? (body.ignoreType = ['whiteList']) : delete body.ignoreType;

    const time = {};
    if (timing.dailyStart && timing.dailyEnd) {
      const dailyStart = timing.dailyStart;
      const dailyEnd = timing.dailyEnd;
      time.dailyStart = dailyStart.format('HH:mm');
      time.dailyEnd = dailyEnd.format('HH:mm');
    } else {
      delete time.dailyStart;
      delete time.dailyEnd;
    }

    if (startAt) {
      time.startAt = startAt.format('YYYY-MM-DD HH:mm:ss');
    }
    if (endAt) {
      time.endAt = endAt.format('YYYY-MM-DD HH:mm:ss');
    }
    body.timing = { ...time };
    //  选择周期
    if (isCycle) {
      body.intervalTime = intervalTime;
      body.intervalUnit = intervalUnit;
    }

    // 如果是勾选目标下发
    if (siteIdList && siteIdList.length > 0) {
      body.target.queryType = 'siteIdList';
      body.target.siteIdList = siteIdList;
      delete body.target.list;
    }

    // 如果是仪表盘下发
    if (['notUpdateIn1Days', 'notUpdateIn7Days', 'notUpdateIn30Days'].includes(typeName)) {
      body.target.queryType = typeName;
    }

    // 如果漏扫策略为自动匹配
    if (selectedTemplateId === '00' && typeName === 'VulDetect') {
      body.oneday = { queryType: 'affectedByTarget' };
      delete body.templateId;
      delete body.detectionPolicy;
    }
    // 如果是集群 node默认为auto interface_type默认为'work'
    if (hasCluster) {
      body.node = scanNodes;

      body.interface_type = 'work';
    } else {
      body.node = 'local';

      body.interface_type = interfaces;
    }
    api(body)
      .then(() => {
        message.success('下发任务成功');
        // 更新下发任务配置缓存
        loadDetectionCache();
        confirm({
          title: `创建${typeName === 'Zoomeye' ? '资产探测' : '漏洞下发'}任务成功`,
          content: '是否继续创建?',
          cancelText: '跳转任务列表',
          okText: '继续创建',
          icon: <Icon type="check-circle" style={{ color: 'green' }} />,
          onOk() {
            callback();
          },
          onCancel() {
            history.push('/task-manage');
          }
        });
      })
      .catch(error => {
        message.error(_.get(error, 'type') === 'parsed' ? error.message : '下发任务失败');
      });
  };

  // 探测目标
  const renderTarget = () => {
    const disabled = isSelectVulTask;
    if (disabled) {
      return (
        <React.Fragment>
          <TextArea
            disabled={disabled}
            className="target-ips"
            value={description || _.join(ips, '\n')}
            rows={5}
            placeholder={descriptions.customIpsPlaceholder}
            onChange={onTargetsChange}
          />
          {errors.ipsError && <p className="validate-error">{errors.ipsError}</p>}
        </React.Fragment>
      );
    }
    if (queryType === 'custom') {
      return (
        <React.Fragment>
          <TextArea
            className="target-ips"
            value={!allSite ? _.join(ips, '\n') : allSiteTitle}
            rows={5}
            disabled={allSite}
            placeholder={descriptions.customIpsPlaceholder}
            onChange={onTargetsChange}
          />
          {<p className="validate-error">{errors.ipsError}</p>}
        </React.Fragment>
      );
      // 勾选目标组情况
    } else if (queryType === 'targetGroup') {
      const selectedIpRanges = _.filter(ipRanges, range =>
        _.includes(selectedIpRangesKeys, range._id)
      );
      const ips = _.join(_.flatten(_.map(selectedIpRanges, 'ips')), '\n');
      return (
        <React.Fragment>
          <TextArea
            className="target-ips ip-ranges"
            value={ips}
            rows={5}
            placeholder={descriptions.customIpsPlaceholder}
            onChange={onTargetsChange}
          />
          {errors.ipRangesError && <p className="validate-error">{errors.ipRangesError}</p>}
        </React.Fragment>
      );
    } else {
      return null;
    }
  };

  // 任务类型
  const renderTaskType = () => {
    return (
      <>
        <div className={cn('item', 'task-type')}>
          <span className="item-title">任务类型</span>
          <RadioGroup
            className="task-type-group"
            value={isCycle ? 'true' : 'false'}
            onChange={e => setIsCycle(e.target.value === 'true')}
          >
            <Radio value="false">单次</Radio>
            <Radio value="true">周期</Radio>
          </RadioGroup>
        </div>
        {isCycle && (
          <div className="cycle-config">
            <InputNumber
              min={0}
              value={intervalTime}
              onChange={value => {
                let intervalTime = value;
                if (intervalTime <= 1) {
                  intervalTime = 1;
                } else {
                  intervalTime = Math.floor(intervalTime);
                }
                setIntervalTime(intervalTime);
              }}
            />
            <Select
              value={intervalUnit}
              onChange={intervalUnit => setIntervalUnit(intervalUnit)}
              getPopupContainer={triggerNode => triggerNode.parentNode}
              style={{ width: 60 }}
            >
              <Select.Option value="hour">时</Select.Option>
              <Select.Option value="day">日</Select.Option>
              <Select.Option value="week">周</Select.Option>
              <Select.Option value="month">月</Select.Option>
            </Select>
          </div>
        )}
      </>
    );
  };
  // 漏扫策略
  const renderMissedScanStrategy = () => {
    return (
      <>
        <div className={'item'}>
          <span className="item-title">漏洞策略</span>
          <Select
            value={selectedTemplateId}
            onChange={onChangeTemplate}
            className="template-selects"
            placeholder="选择漏洞策略模板"
            style={{ width: 400 }}
          >
            {strategyTemplates.map(({ name, _id }) => (
              <Select.Option key={_id} value={_id}>
                {name}
              </Select.Option>
            ))}
          </Select>
          <Link
            to="/asset-config/strategy-template"
            style={{ display: 'block', marginTop: 8, marginLeft: 10 }}
            target="_blank"
          >
            配置漏洞策略模板
          </Link>
        </div>
        {selectedTemplateId === '01' ? (
          <CheckboxSelect
            className="selected-onedays"
            placeholder="请输入插件名称进行搜索"
            options={onedays}
            selected={selectedOnedays}
            onChange={onSelectOnedays}
            allButton={false}
            style={{ width: 400 }}
          />
        ) : null}
      </>
    );
  };

  // 获取漏扫策略数据
  const loadAllStrategyTemplates = () => {
    getAllStrategies().then(res => {
      const strategyTemplates = _.get(res, 'data.data.list', []);
      strategyTemplates.unshift({ name: '自动匹配', _id: '00' });
      strategyTemplates.push({ name: '自定义', _id: '01' });
      setStrategyTemplates(strategyTemplates);
      setSelectedTemplateId('00');
    });
  };

  const netConfigList = () => {
    getNetConfig().then(res => {
      let list = [];
      list = JSON.parse(_.get(res, 'data.data.result.message', []));
      const filterList = list
        .filter(r => r.name !== 'mgmt')
        .map(r => {
          r.title = r.name?.includes('work') ? `工作口/${r.rawname}` : `扫描口/${r.rawname}`;
          return r;
        });
      setInterfacesList(filterList);
    });
  };

  useEffect(() => {
    allDicts();
    loadAllStrategyTemplates();
    netConfigList();
    typeName === 'VulDetect' && loadOnedays();
  }, []);

  useEffect(() => {
    checkTime();
  }, [startAt, endAt, timing]);

  useEffect(() => {
    if (interfacesList.length > 0) {
      setInterfaces(_.get(interfacesList[0], 'rawname', ''));
    }
  }, [interfacesList]);

  // 监听是否为勾选资产管理传入
  useEffect(() => {
    if (sites && sites.length > 0) {
      setIsSelectVulTask(true);
      const currentSelectedSiteUrlIps = _.filter(
        _.flatten(
          _.map(sites, site => {
            return [site.name, site.ipv6 || site.ip, site.url].reduce((sum, item) => {
              return sum ? { true: sum + `(${item})`, false: sum }[Boolean(item)] : item;
            });
          })
        ),
        target => !_.isEmpty(target)
      );
      setSiteIdList(_.map(sites, site => site._id));
      setIps(currentSelectedSiteUrlIps);
    }
  }, [sites]);
  useEffect(() => {
    if (['notUpdateIn1Days', 'notUpdateIn7Days', 'notUpdateIn30Days'].includes(typeName)) {
      setIsSelectVulTask(true);
    }
  }, [typeName]);

  return (
    <div className={prefixCls}>
      <Spin spinning={ipRangesSpinning}>
        <div className={prefixCls + '-box'}>
          <div className={'item'}>
            <span className="item-title required">任务名称</span>
            <Input
              placeholder={descriptions.taskNamePlaceholder}
              value={name}
              onChange={onNameChange}
            />
          </div>
          {errors.nameError && <p className="validate-error name-error">{errors.nameError}</p>}
          <div className={cn('item', 'goal-title')}>
            <span className="item-title required">
              探测目标
              <Tooltip title={descriptions.targetLimit}>
                <Icon type="exclamation-circle" />
              </Tooltip>
            </span>
            {!isSelectVulTask && (
              <>
                <RadioGroup className="goal-type" value={queryType} onChange={onTargetTypeChange}>
                  <Radio value="custom">自定义</Radio>
                  <Radio value="targetGroup">选择目标组</Radio>
                </RadioGroup>
                <span className="clear" onClick={clearTarget}>
                  <img src={EraserPng} alt="" />
                  清空
                </span>
              </>
            )}
          </div>
          <div className="render-target" style={{ marginTop: isSelectVulTask ? -30 : 0 }}>
            {renderTarget()}
          </div>
          <div className="probe-strategy">
            <RenderProbeStrategy typeName={typeName} ref={RenderProbeStrategyRef} />
          </div>
          <div className="missed-scan-strategy">
            {typeName === 'VulDetect' && renderMissedScanStrategy()}
          </div>
          <div className="dist">{typeName === 'WeakPassword' && renderDist()}</div>
          <ScanRate ref={ScanRateRef} />
          <div>{renderTaskType()}</div>
          <div className={cn('item', 'date-range')}>
            <span className="item-title">
              定时设置
              <Tooltip title={descriptions.dateLimit}>
                <Icon type="exclamation-circle" />
              </Tooltip>
            </span>
            <TaskLimitDate
              onDateStartChange={onDateStartChange}
              onDateEndChange={onDateEndChange}
            />
          </div>
          <div className={cn('item', 'time-range')}>
            <span className="item-title">
              每日允许时间段
              <Tooltip title={descriptions.timeLimit}>
                <Icon type="exclamation-circle" />
              </Tooltip>
            </span>
            <div className="time-picker-range">
              <TimePicker
                className="daily-start"
                placeholder="开始时间"
                format="HH:mm"
                style={{ width: 195 }}
                value={timing.dailyStart}
                onChange={time => onTimeRangeChange('dailyStart', time)}
                getPopupContainer={triggerNode => triggerNode.parentNode}
              />
              &nbsp;&nbsp;
              <TimePicker
                className="daily-end"
                placeholder="结束时间"
                format="HH:mm"
                style={{ width: 195 }}
                value={timing.dailyEnd}
                onChange={time => onTimeRangeChange('dailyEnd', time)}
                getPopupContainer={triggerNode => triggerNode.parentNode}
              />
            </div>
          </div>
          {
            <p className="validate-error time-range-error">
              {errors.timeRangeError || errors.detectionTimeError}
            </p>
          }
          {/* 当是集群证书，有扫描节点的时候 */}
          {isCluster && hasCluster && (
            <div className={cn('item', 'interface-title')}>
              <span className="item-title required">扫描节点</span>
              <Select
                onChange={e => setInterfaces(e)}
                value={scanNodes}
                getPopupContainer={triggerNode => triggerNode.parentNode}
                style={{ width: 400 }}
              >
                {scanList.map(item => {
                  return (
                    <Select.Option value={item.value} key={item.value}>
                      {item.label}
                    </Select.Option>
                  );
                })}
              </Select>
            </div>
          )}
          {/* 非集群/集群+无扫描节点 */}
          {(!isCluster || (isCluster && !hasCluster)) && (
            <div className={cn('item', 'interface-title')}>
              <span className="item-title required">扫描网口</span>
              <Select
                onChange={e => setInterfaces(e)}
                value={interfaces}
                getPopupContainer={triggerNode => triggerNode.parentNode}
                style={{ width: 400 }}
              >
                {interfacesList.map(item => {
                  return (
                    <Select.Option value={item.rawname} key={item.rawname}>
                      {item.title}
                    </Select.Option>
                  );
                })}
              </Select>
            </div>
          )}

          <div className={cn('item', 'pripority')}>
            <span className="item-title">优先级</span>
            <RadioGroup
              className="priority-group"
              value={priority}
              onChange={e => setPriority(e.target.value)}
            >
              {Object.keys(TASK_PRIORITY_MAP).map(key => (
                <Radio key={key} value={key}>
                  {TASK_PRIORITY_MAP[key]}
                </Radio>
              ))}
            </RadioGroup>
          </div>
          <div className={cn('item', 'pripority')}>
            <span className="item-title">国产化识别</span>
            <Checkbox.Group
              className="Checkbox-group"
              style={{ width: 365 }}
              disabled
              options={[
                { label: '系统软件', value: '0' },
                { label: '数据库', value: '1' },
                { label: '操作系统', value: '2' },
                { label: '硬件设备', value: '3' }
              ]}
              defaultValue={['0', '1', '2', '3']}
            />

            <NavLink style={{ marginLeft: 10 }} to={'/knowledge-base/localized'} target="_blank">
              查看清单识别
            </NavLink>
          </div>
          <div className={cn('item')}>
            <span className="item-title">禁扫目标</span>
            <Checkbox
              value={ignoreType}
              defaultChecked={true}
              onChange={() => setIgnoreType(!ignoreType)}
            />
            <Link to="/asset-config/white-list" style={{ paddingLeft: 8 }}>
              去配置
            </Link>
          </div>
        </div>
      </Spin>
      <div className="footer">
        <Button type="primary" size={'large'} onClick={submit}>
          下发任务
        </Button>
      </div>

      <Modal
        maskClosable={false}
        title="选择目标组"
        visible={ipRangesModalVisible}
        destroyOnClose={true}
        className={cn('ip-range-select', 'no-header-bottom-lines', 'bottom-center', 'padding-24')}
        onCancel={() => {
          setIpRangesModalVisible(false);
        }}
        onOk={() => setIpRangesModalVisible(false)}
      >
        <Spin tip="加载中" spinning={ipRangesSpinning}>
          <CheckboxSelect
            placeholder="请输入关键词搜索"
            onChange={selectedIpRangesKeys => setSelectedIpRangesKeys(selectedIpRangesKeys)}
            options={ipRanges}
            selected={selectedIpRangesKeys}
          />
        </Spin>
        <a className="to-target-manage" href="/asset-config/target-manage" target="_blank">
          前往进行目标组管理
        </a>
      </Modal>
    </div>
  );
};

AppTaskForm.propTypes = {
  allSite: PropTypes.Boolean,
  allSiteTitle: PropTypes.string,
  history: PropTypes,
  templates: PropTypes.array,
  typeName: PropTypes.string,
  loadDetectionCache: PropTypes.func,
  callback: PropTypes.func,
  sites: PropTypes.array,
  description: PropTypes.string,
  isCluster: PropTypes.Boolean,
  hasCluster: PropTypes.Boolean
};

const mapStateToProps = state => {
  return {
    templates: _.get(state, 'assetManage.templates', []),
    hasCluster: _.get(state, 'auth.cert.is_cluster', false),
    isCluster: _.includes(state?.auth?.cert?.modules, 'distribute')
  };
};

const mapDispatchToProps = dispatch => {
  return {
    ...bindActionCreators(assetManageActions, dispatch)
  };
};
export default withRouter(
  connect(
    mapStateToProps,
    mapDispatchToProps
  )(AppTaskForm)
);
